//**************************************************************************************************************
// CLASS: Assembler
//
// DESCRIPTION
// Main class for the K1 assembler.
//
// AUTHOR INFORMATION
// Group 2
// Tyler Williams
// Lauren Walker
// Cameron Stewart
// Fatimah Alowah
//**************************************************************************************************************
// Write the preprocessor guard.
#ifndef __ASSEMBLER_HPP__
#define __ASSEMBLER_HPP__

#include "DataSegment.hpp"
#include "Instr.hpp"
#include "InstrTypeB.hpp"
#include "InstrTypeR.hpp"
#include "InstrTypeRI.hpp"
#include "InstrTypeRV.hpp"
#include "Lex.hpp"
#include "TextSegment.hpp"
#include "Types.hpp"
#include <cstdlib>
#include <string.h>
#include <cstring>
#include <string>
//==============================================================================================================
// CLASS: Assembler
//==============================================================================================================

// Write the class declaration for Assembler.
class Assembler {
public:
    Assembler
    (
     std::string pSrcFname,
     std::string pBinFname
     );
    
    ~Assembler
    (
    );
    
    int Run
    (
    );
    
protected:
    void Assemble
    (
     uint const pPass
     );
    
    void AssembleDirective
    (
     std::string const& pDirective
     );
    
    Instr *AssembleInstr
    (
     std::string const& pMnemonic,
     std::string const& pLabel = ""
     );
    
    Instr *AssembleInstrTypeB
    (
     std::string const& pMnemonic,
     std::string const& pLabel = ""
     );
    
    Instr *AssembleInstrTypeN
    (
     std::string const& pMnemonic,
     std::string const& pLabel = ""
     );
    
    Instr *AssembleInstrTypeR
    (
     std::string const& pMnemonic,
     std::string const& pLabel = ""
     );
    
    Instr *AssembleInstrTypeRI
    (
     std::string const& pMnemonic,
     std::string const& pLabel = ""
     );
    
    Instr *AssembleInstrTypeRV
    (
     std::string const& pMnemonic,
     std::string const& pLabel = ""
     );
    
    void AssembleLabel
    (
     std::string const& pName
     );
    
    void AssembleVariable
    (
     std::string const& pName
     );
    
    void WriteBinary
    (
    ) const;
    
private:
    std::string mBinFname;
    uint32      mCurrAddr;
    DataSegment mDataSeg;
    Lex         mLex;
    std::string mSrcFname;
    TextSegment mTextSeg;
    
    Assembler();
    
    Assembler
    (
     Assembler const& pAssembler
     );
    
    Assembler& operator=
    (
     Assembler const& pAssembler
     );
};

// End the preprocessor guard.
#endif
